const socket = require('socket.io')
const util = require('util')
// 引入 db 文件
const { db } = require('../utils/db')

// 将db.query转换为返回Promise的函数
const queryPromise = util.promisify(db.query).bind(db)
const {
  insertRoomParticipantsTableSql,
  deleteAllRoomParticipantsSql,
  insertRoomChatTableSql
} = require('../sql/roomGroup')

function initializeSocketServer(server) {
  // 房间列表
  let rooms = {}
  const io = socket(server, {
    cors: {
      origin: '*' // 配置跨域
    }
  })
  io.on('connection', sock => {
    console.log('连接成功...')
    // 监听创建房间事件
    sock.on('createRoom', async (roomId, account, avatar) => {
      console.log(`用户 ${sock.id} 创建房间 ${roomId}`)
      sock.join(roomId)

      // 首先要清空房间人数
      await queryPromise(deleteAllRoomParticipantsSql, [parseInt(roomId)])

      // 向房间人数表添加记录
      await queryPromise(insertRoomParticipantsTableSql, [
        parseInt(roomId),
        parseInt(roomId),
        sock.id,
        account,
        avatar
      ])
      // 获取当前房间中的所有 Socket
      const roomClients = io.sockets.adapter.rooms.get(roomId)
      // 遍历房间中的所有 Socket
      roomClients.forEach((_, socketId) => {
        // 如果不是当前 Socket，则断开连接
        if (!sock.rooms.has(socketId)) {
          io.sockets.sockets.get(socketId)?.disconnect(true)
        }
      })
      rooms[roomId] = []
      const numClients = roomClients ? roomClients.size : 0
      rooms[roomId].push({
        id: sock.id,
        account,
        avatar
      })
      console.log(rooms)
    })
    // 监听加入房间的事件
    sock.on('joinRoom', async (roomId, account, avatar) => {
      console.log(`用户 ${sock.id} 加入房间 ${roomId}`)
      sock.join(roomId)
      // 向房间人数表添加记录
      await queryPromise(insertRoomParticipantsTableSql, [
        parseInt(roomId),
        parseInt(roomId),
        sock.id,
        account,
        avatar
      ])

      // 获取当前房间中的所有的 Socket
      const roomClients = io.sockets.adapter.rooms.get(roomId)
      if (roomClients.size === 1) return

      // 获取房间数量
      const numClients = roomClients ? roomClients.size : 0
      let arr = rooms[roomId].filter(v => {
        return v.account === account
      })
      if (arr.length === 0) {
        rooms[roomId].push({
          id: sock.id,
          account,
          avatar
        })
      }

      console.log(rooms[roomId])
      /**
       * rooms[roomId] 房间成员列表
       * account 用户名
       * avatar 用户头像
       * sock.id 本机id
       */
      io.emit('joined', rooms[roomId], account, sock.id)
    })

    // 监听离开房间的事件
    sock.on('leaveRoom', (roomId, account) => {
      console.log(`用户 ${sock.id} 离开房间 ${roomId}`)
      // 从 rooms 中删除对应的用户
      rooms[roomId] = rooms[roomId].filter(user => {
        return user.account !== account
      })
      // 发送 leave 消息给自己和房间中的其他客户端
      io.to(roomId).emit('leaved', roomId, sock.id, account)
      sock.leave(roomId)
      sock.disconnect(true)
    })

    // 监听结束会议事件
    sock.on('endRoom', roomId => {
      console.log(`房间 ${roomId} 结束`)

      // 发送 endRoom 消息给自己和房间中的其他客户端
      io.to(roomId).emit('endRoom')
    })

    // 交换 SDP信息 和 candidate 信息
    sock.on('message', (_unique, roomId, msg) => {
      // 当收到消息时，将消息发送给指定房间
      sock.to(roomId).emit('message', _unique, roomId, msg)
    })

    // 发送聊天信息
    sock.on(
      'commentMsg',
      async (account, roomId, msg, messageType, recipientType) => {
        // 根据账户名找到userId
        const userId = rooms[roomId].filter(item => {
          return item.account === account
        })[0].id
        // 向数据库添加聊天记录
        await queryPromise(insertRoomChatTableSql, [
          parseInt(roomId),
          parseInt(roomId),
          userId,
          account,
          msg,
          messageType,
          JSON.stringify(recipientType)
        ])
        io.to(roomId).emit('commentMsg', recipientType, account)
      }
    )
  })
}

module.exports = initializeSocketServer
